import { onMounted, onUnmounted } from 'vue'

export function useParallax() {
  const sections = []
  let ticking = false
  let lastScrollY = window.scrollY
  let rafId = null

  // 添加缓动函数
  const easeOutCubic = (t) => 1 - Math.pow(1 - t, 3)

  const initSection = (el, options = {}) => {
    const {
      start = 'top center',
      end = 'bottom center',
      properties = [
        {
          startValue: 0,
          endValue: 1,
          property: 'opacity'
        }
      ],
      easing = easeOutCubic
    } = options

    const section = {
      el,
      start,
      end,
      properties,
      easing,
      startScrollY: 0,
      endScrollY: 0,
      progress: 0,
      currentValues: properties.reduce((acc, prop) => {
        acc[prop.property] = prop.startValue
        return acc
      }, {})
    }

    sections.push(section)
    calculateSectionScrollPositions(section)
    updateSection(section)
    return section
  }

  const calculateSectionScrollPositions = (section) => {
    const { el, start, end } = section
    const viewportHeight = window.innerHeight
    const rect = el.getBoundingClientRect()
    const scrollY = window.scrollY

    const [startElement, startViewport] = start.split(' ')
    const startY = startElement === 'top' ? rect.top + scrollY : rect.bottom + scrollY
    const startViewportY = startViewport === 'top' ? 0 : startViewport === 'center' ? viewportHeight / 2 : viewportHeight
    section.startScrollY = startY - startViewportY

    const [endElement, endViewport] = end.split(' ')
    const endY = endElement === 'top' ? rect.top + scrollY : rect.bottom + scrollY
    const endViewportY = endViewport === 'top' ? 0 : endViewport === 'center' ? viewportHeight / 2 : viewportHeight
    section.endScrollY = endY - endViewportY
  }

  const lerp = (start, end, t) => start * (1 - t) + end * t

  const updateSection = (section) => {
    const { startScrollY, endScrollY, properties, easing } = section
    const scrollY = window.scrollY

    // 计算原始进度
    const rawProgress = Math.max(0, Math.min(1, (scrollY - startScrollY) / (endScrollY - startScrollY)))
    // 应用缓动函数
    section.progress = easing(rawProgress)

    // 应用属性变化
    properties.forEach(({ startValue, endValue, property }) => {
      // 使用线性插值计算目标值
      const targetValue = startValue + (endValue - startValue) * section.progress
      
      // 平滑过渡到目标值
      section.currentValues[property] = lerp(
        section.currentValues[property], 
        targetValue,
        0.1 // 调整这个值可以改变动画的平滑度
      )

      const value = section.currentValues[property]

      switch (property) {
        case 'translateY':
          section.el.style.transform = `translate3d(0, ${value}px, 0)`
          break
        case 'translateX':
          section.el.style.transform = `translate3d(${value}px, 0, 0)`
          break
        case 'scale':
          section.el.style.transform = `scale(${value})`
          break
        case 'opacity':
          section.el.style.opacity = value
          break
        case 'blur':
          section.el.style.filter = `blur(${value}px)`
          break
      }
    })

    // 如果还没有达到目标值，继续更新
    if (section.properties.some(({ property }) => 
      Math.abs(section.currentValues[property] - (startValue + (endValue - startValue) * section.progress)) > 0.001
    )) {
      rafId = requestAnimationFrame(() => updateSection(section))
    }
  }

  const onScroll = () => {
    if (!ticking) {
      cancelAnimationFrame(rafId)
      rafId = requestAnimationFrame(() => {
        sections.forEach(section => {
          calculateSectionScrollPositions(section)
          updateSection(section)
        })
        ticking = false
      })
      ticking = true
    }
  }

  const onResize = () => {
    sections.forEach(calculateSectionScrollPositions)
  }

  onMounted(() => {
    window.addEventListener('scroll', onScroll, { passive: true })
    window.addEventListener('resize', onResize)
    onScroll()
  })

  onUnmounted(() => {
    window.removeEventListener('scroll', onScroll)
    window.removeEventListener('resize', onResize)
    cancelAnimationFrame(rafId)
  })

  return {
    initSection
  }
}
